# Description
Luogu 传送门
# Solution
我们直接找是否有等于 3 的等差子序列即可。
假设三个数 形成了等差子序列,那么有 ,所以对于一个 对应的 只有一个。
因此我们对于每一个 只需要判断一对 是否在 的两边。
如何判断呢?很简单。
我们开一个权值线段树,依次往里面插入数,把相应的位置赋值为 1。
假设已经枚举到了第 个数,此时 都已经在权值线段树里面了。
我们只需要判断 和 的 hash 值一不一样即可( 为权值线段树, 防止越界)。
思考一下这样为什么是正确的。
假设 hash 值一样,表示所有能与 配对的 都已经在 出现过了,自然不可能组成等差子序列。
反之自然可以。
# Code
#include <bits/stdc++.h> | |
#define uint unsigned int | |
using namespace std;  | |
namespace IO{  | |
inline int read(){  | |
int x = 0;  | |
char ch = getchar();  | |
while(!isdigit(ch)) ch = getchar();  | |
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();  | |
return x;  | |
    } | |
template <typename T> inline void write(T x){  | |
if(x > 9) write(x / 10);  | |
putchar(x % 10 + '0');  | |
    } | |
} | |
using namespace IO;  | |
const int N = 1e4 + 10;  | |
int T, n;  | |
int a[N];  | |
uint h1[N << 2], h2[N << 2], fx[N];  | |
#define ls rt << 1 | |
#define rs rt << 1 | 1 | |
#define mid ((l + r) >> 1) | |
inline void pushup(int l, int r, int rt){  | |
h1[rt] = h1[ls] * fx[r - mid] + h1[rs];  | |
h2[rt] = h2[rs] * fx[mid - l + 1] + h2[ls];  | |
} | |
inline void update(int k, int l, int r, int rt){  | |
if(l > r || !rt) return;  | |
if(l == r) return h1[rt] = h2[rt] = 1, void();  | |
if(k <= mid) update(k, l, mid, ls);  | |
else update(k, mid + 1, r, rs);  | |
pushup(l, r, rt);  | |
} | |
inline uint query1(int L, int R, int l, int r, int rt){  | |
if(L > R || !rt) return 0;  | |
if(L == l && r == R) return h1[rt];  | |
if(R <= mid) return query1(L, R, l, mid, ls);  | |
else if(L > mid) return query1(L, R, mid + 1, r, rs);  | |
else return query1(L, mid, l, mid, ls) * fx[R - mid] + query1(mid + 1, R, mid + 1, r, rs);  | |
} | |
inline uint query2(int L, int R, int l, int r, int rt){  | |
if(L > R || !rt) return 0;  | |
if(L == l && r == R) return h2[rt];  | |
if(R <= mid) return query2(L, R, l, mid, ls);  | |
else if(L > mid) return query2(L, R, mid + 1, r, rs);  | |
else return query2(mid + 1, R, mid + 1, r, rs) * fx[mid - L + 1] + query2(L, mid, l, mid, ls);  | |
} | |
int main(){  | |
T = read();  | |
fx[0] = 1;  | |
for(int i = 1; i < N; ++i) fx[i] = fx[i - 1] * 19;  | |
while(T--){  | |
memset(h1, 0, sizeof(h1));  | |
memset(h2, 0, sizeof(h2));  | |
n = read();  | |
for(int i = 1; i <= n; ++i) a[i] = read();  | |
bool flag = 0;  | |
for(int i = 1; i <= n; ++i){  | |
int len = min(a[i] - 1, n - a[i]);  | |
if(query1(a[i] - len, a[i] - 1, 1, n, 1) != query2(a[i] + 1, a[i] + len, 1, n, 1)) {flag = 1; break;}  | |
update(a[i], 1, n, 1);  | |
        } | |
puts(flag ? "Y" : "N");  | |
    } | |
return 0;  | |
} | |
// X.K. |